package com.duojuhe.websocket;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.duojuhe.coremodule.chat.im.entity.*;
import com.duojuhe.coremodule.chat.im.mapper.*;
import com.duojuhe.coremodule.chat.im.pojo.dto.chatgroup.user.ChatGroupUserRes;
import com.duojuhe.coremodule.chat.im.pojo.dto.talkrecord.forward.ForwardSnapshotRecordRes;
import com.duojuhe.coremodule.chat.im.pojo.dto.talkrecord.forward.MultiForwardRecordRes;
import com.duojuhe.coremodule.chat.im.pojo.dto.talkrecord.sendtalk.ForwardTalkRecordReq;
import com.duojuhe.coremodule.chat.im.pojo.dto.talkrecord.sendtalk.SendTalkReq;
import com.duojuhe.coremodule.chat.im.pojo.dto.usersfriends.ChatUsersFriendsRes;
import com.duojuhe.websocket.subscriber.SendChatSubscribeUtil;
import com.duojuhe.websocket.subscriber.SubscribeHandleDto;
import com.duojuhe.websocket.subscriber.message.keyboard.KeyboardMessageDto;
import com.duojuhe.websocket.subscriber.message.online.OnlineStatusMessageDto;
import com.duojuhe.websocket.subscriber.message.talk.ChatTalkRecordDto;
import com.duojuhe.websocket.subscriber.message.talk.TalkMessageDto;
import com.duojuhe.websocket.subscriber.message.talk.MessageBodyRes;
import com.duojuhe.websocket.subscriber.message.talk.bean.*;
import com.duojuhe.websocket.subscriber.message.talk.bean.vote.AnswerOptionRes;
import com.duojuhe.websocket.subscriber.message.talk.bean.vote.DetailRes;
import com.duojuhe.websocket.subscriber.message.talk.bean.vote.StatisticsRes;
import com.duojuhe.common.constant.SingleStringConstant;
import com.duojuhe.common.enums.chat.ImChatEnum;
import com.duojuhe.common.exception.base.DuoJuHeException;
import com.duojuhe.common.result.ErrorCodes;
import com.duojuhe.common.result.ServiceResult;
import com.duojuhe.common.utils.encryption.md5.MD5Util;
import com.duojuhe.common.utils.idgenerator.UUIDUtils;
import com.duojuhe.common.utils.thread.ThreadUtils;
import com.duojuhe.coremodule.system.entity.SystemUser;
import com.duojuhe.coremodule.system.mapper.SystemUserMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class MessageHandleService {
    @Resource
    private SendChatSubscribeUtil sendChatSubscribeUtil;
    @Resource
    private ChatGroupUserMapper chatGroupUserMapper;
    @Resource
    private ChatUsersFriendsMapper chatUsersFriendsMapper;
    @Resource
    private SystemUserMapper systemUserMapper;
    @Resource
    private ChatTalkRecordMapper chatTalkRecordMapper;
    @Resource
    private ChatTalkRecordFileMapper chatTalkRecordFileMapper;
    @Resource
    private ChatTalkRecordForwardMapper chatTalkRecordForwardMapper;
    @Resource
    private ChatTalkRecordCodeMapper chatTalkRecordCodeMapper;
    @Resource
    private ChatTalkRecordInviteMapper chatTalkRecordInviteMapper;
    @Resource
    private ChatTalkRecordVoteMapper chatTalkRecordVoteMapper;
    @Resource
    private ChatTalkRecordVoteAnswerMapper chatTalkRecordVoteAnswerMapper;
    @Resource
    private ChatUsersChatListMapper chatUsersChatListMapper;
    @Resource
    private ChatGroupMapper chatGroupMapper;
    /**
     * 添加聊天记录
     * @param jsonObject
     */
    @Transactional(rollbackFor = Exception.class)
    public void onConsumeTalk(JSONObject jsonObject, SocketSessionUser socketSessionUser){
        try {
            if (jsonObject==null){
                throw new DuoJuHeException(ErrorCodes.CHAT_SEND_TALK_MESSAGE_FALL);
            }
            //当前用户id
            String userId = socketSessionUser.getUserId();
            //获取消息内容
            JSONObject jsonData = jsonObject.getJSONObject("data");
            if (jsonData==null){
                throw new DuoJuHeException(ErrorCodes.SOCKET_REQUEST_BODY_ERROR);
            }
            //发送者id
            String senderId = jsonData.getString("senderId");
            //接收对象id
            String receiverId = jsonData.getString("receiverId");
            //聊天类型
            Integer talkType = jsonData.getInteger("talkType");
            //消息内容
            String textMessage = jsonData.getString("textMessage");
            if (StringUtils.isBlank(senderId)||StringUtils.isBlank(receiverId)||StringUtils.isBlank(textMessage)||talkType==null){
                throw new DuoJuHeException(ErrorCodes.SOCKET_REQUEST_BODY_ERROR);
            }
            //聊天类型
            //群聊
            Integer groupChat = ImChatEnum.TalkType.GROUP_CHAT.getKey();
            //私聊
            Integer privateChat = ImChatEnum.TalkType.PRIVATE_CHAT.getKey();
            if (!groupChat.equals(talkType)&&!privateChat.equals(talkType)){
                throw new DuoJuHeException(ErrorCodes.SOCKET_REQUEST_BODY_ERROR);
            }
            //检测判断发送者是否是当前用户
            if (!userId.equals(senderId)){
                throw new DuoJuHeException("["+textMessage+"]发送者参数错误!");
            }
            //查询发送者信息
            SystemUser systemUser = systemUserMapper.selectByPrimaryKey(userId);
            if (systemUser==null){
                throw new DuoJuHeException("["+textMessage+"]发送者参数错误!");
            }
            //消息类型
            Integer msgType = ImChatEnum.TalkMessageType.TEXT_MESSAGE.getKey();
            //构建消息记录
            SendTalkReq req = new SendTalkReq();
            req.setReceiverId(receiverId);
            req.setTalkType(talkType);
            ChatTalkRecord record = buildChatTalkRecord(msgType,req,systemUser);
            record.setContent(textMessage);
            //保存消息记录
            chatTalkRecordMapper.insertSelective(record);
            //保存最后的消息记录
            handleLastMessage(record);
            //发送消息到各个订阅端
            handleSendChatSubscribe(BuildMessageUtils.buildMessageBodyRes(record));
        }catch (Exception e){
            if (e instanceof DuoJuHeException) {
                throw new DuoJuHeException(e.getMessage());
            } else {
                throw new DuoJuHeException(ErrorCodes.CHAT_SEND_TALK_MESSAGE_FALL);
            }
        }
    }

    /**
     * 检查群组是否被允许发送消息 以下判断群主不受限制
     * @param senderId
     * @param groupId
     */
    public void checkGroupSendMessage(String senderId,String groupId){
        if (StringUtils.isBlank(groupId)||StringUtils.isBlank(senderId)){
            throw new DuoJuHeException(ErrorCodes.CHAT_GROUP_SEND_TALK_MESSAGE_FALL);
        }
        //是否标识
        Integer yes = ImChatEnum.IM_YES_NO.YES.getKey();
        ChatGroup chatGroup = chatGroupMapper.selectByPrimaryKey(groupId);
        if (chatGroup==null){
            throw new DuoJuHeException(ErrorCodes.CHAT_GROUP_SEND_TALK_MESSAGE_FALL);
        }
        //群名称
        String groupNameText = "【"+chatGroup.getGroupName()+"】";
        //以下判断群主不受限制
        String id = MD5Util.getMD532(senderId+groupId);
        //检查当前发布用户是否在群组内
        ChatGroupUser chatGroupUser = chatGroupUserMapper.selectByPrimaryKey(id);
        if (chatGroupUser==null){
            throw new DuoJuHeException(groupNameText+ErrorCodes.CHAT_GROUP_SEND_TALK_MESSAGE_FALL.getMessage());
        }
        if (yes.equals(chatGroupUser.getIsMute())){
            throw new DuoJuHeException(groupNameText+ErrorCodes.CHAT_GROUP_USER_MUTE_ERROR.getMessage());
        }
        if (yes.equals(chatGroupUser.getIsQuit())){
            throw new DuoJuHeException(groupNameText+ErrorCodes.CHAT_GROUP_USER_QUIT_ERROR.getMessage());
        }
        //如果不是普通成员则不进行下列验证
        if (!ImChatEnum.GroupUser.MEMBER.getKey().equals(chatGroupUser.getLeader())){
            return;
        }
        if (!yes.equals(chatGroup.getIsOvert())){
            throw new DuoJuHeException(groupNameText+ErrorCodes.CHAT_GROUP_SEND_TALK_MESSAGE_FALL.getMessage());
        }
        if (yes.equals(chatGroup.getIsDismiss())){
            throw new DuoJuHeException(groupNameText+ErrorCodes.CHAT_GROUP_DISMISS_ERROR.getMessage());
        }
        if (yes.equals(chatGroup.getIsMute())){
            throw new DuoJuHeException(groupNameText+ErrorCodes.CHAT_GROUP_MUTE_ERROR.getMessage());
        }
    }


    /**
     * 构建校验好友或群组基础信息
     * @return
     */
    public ChatTalkRecord buildChatTalkRecord(Integer msgType, SendTalkReq sendTalk,SystemUser systemUser){
        //当前登录人
        String userId = systemUser.getUserId();
        //接受者
        String receiverId  = sendTalk.getReceiverId();
        //聊天类型
        Integer talkType = sendTalk.getTalkType();
        //发送者姓名
        String realName = systemUser.getRealName();
        //发送者头像
        String headPortrait = systemUser.getHeadPortrait();
        //分组名称
        String groupName = "";
        //分组头像
        String groupAvatar = "";
        //主键ID 当前用户id和接收id的MD5值
        String id = MD5Util.getMD532(userId+receiverId);
        if (ImChatEnum.TalkType.PRIVATE_CHAT.getKey().equals(talkType)){
            ChatUsersFriendsRes chatUsersFriendsRes = chatUsersFriendsMapper.queryChatUsersFriendsResById(id);
            if (chatUsersFriendsRes==null || !ImChatEnum.IM_YES_NO.YES.getKey().equals(chatUsersFriendsRes.getIsFriend())){
                throw new DuoJuHeException(ErrorCodes.NOT_FRIENDS_NO_TALK_ERROR);
            }
            //发送者姓名
            realName = StringUtils.isBlank(chatUsersFriendsRes.getFriendRemark())?realName:chatUsersFriendsRes.getFriendRemark();
        }else {
            ChatGroupUserRes chatGroupUserRes = chatGroupUserMapper.queryChatGroupUserResById(id);
            if (chatGroupUserRes==null){
                throw new DuoJuHeException(ErrorCodes.NOT_GROUP_USER_NO_TALK_ERROR);
            }
            //判断群组是否被禁言了
            checkGroupSendMessage(userId,receiverId);
            //分组名称
            groupName = chatGroupUserRes.getGroupName();
            //分组头像
            groupAvatar = chatGroupUserRes.getGroupAvatar();
        }
        //消息id
        String recordId = UUIDUtils.getUUID32();
        //当前时间
        Date nowDate = new Date();
        //未处理标识
        Integer no = ImChatEnum.IM_YES_NO.NO.getKey();
        //消息记录
        ChatTalkRecord record = new ChatTalkRecord();
        record.setRecordId(recordId);
        record.setTalkType(talkType);
        record.setMsgType(msgType);
        record.setUserId(userId);
        record.setReceiverId(receiverId);
        record.setIsMark(no);
        record.setIsRead(no);
        record.setIsRevoke(no);
        record.setIsDelete(no);
        record.setUpdateTime(nowDate);
        record.setCreateTime(nowDate);
        record.setCreateUserId(userId);
        record.setContent("");
        record.setReleaseTime(nowDate);
        record.setRealName(realName);
        record.setHeadPortrait(headPortrait);
        record.setGroupName(groupName);
        record.setGroupAvatar(groupAvatar);
        return record;
    }




    /**
     * 构建处理群组通知 消息对象
     * @return
     */
    public ChatTalkRecord buildGroupNoticeChatTalkRecord(Integer msgType, SendTalkReq sendTalk,SystemUser systemUser,ChatGroup group){
        //当前登录人
        String userId = systemUser.getUserId();
        //接受者
        String receiverId  = sendTalk.getReceiverId();
        //聊天类型
        Integer talkType = sendTalk.getTalkType();
        //发送者姓名
        String realName = systemUser.getRealName();
        //发送者头像
        String headPortrait = systemUser.getHeadPortrait();
        //分组名称
        String groupName = group.getGroupName();
        //分组头像
        String groupAvatar = group.getGroupAvatar();
        //消息id
        String recordId = UUIDUtils.getUUID32();
        //当前时间
        Date nowDate = new Date();
        //未处理标识
        Integer no = ImChatEnum.IM_YES_NO.NO.getKey();
        //消息记录
        ChatTalkRecord record = new ChatTalkRecord();
        record.setRecordId(recordId);
        record.setTalkType(talkType);
        record.setMsgType(msgType);
        record.setUserId(userId);
        record.setReceiverId(receiverId);
        record.setIsMark(no);
        record.setIsRead(no);
        record.setIsRevoke(no);
        record.setIsDelete(no);
        record.setUpdateTime(nowDate);
        record.setCreateTime(nowDate);
        record.setCreateUserId(userId);
        record.setContent("");
        record.setReleaseTime(nowDate);
        record.setRealName(realName);
        record.setHeadPortrait(headPortrait);
        record.setGroupName(groupName);
        record.setGroupAvatar(groupAvatar);
        return record;
    }




    /**
     * 校验转发消息参数
     * @param req
     */
    public List<SendTalkReq> verifyForward(String userId, ForwardTalkRecordReq req){
        //校验查询参数
        checkQueryChatTalkRecordParam(userId,req.getTalkType(),req.getReceiverId());
        //转发接收用户集合
        List<String> receiveUserIdList = req.getReceiveUserIdList();
        //转发接收群组集合
        List<String> receiveGroupIdList = req.getReceiveGroupIdList();
        if ((receiveUserIdList==null||receiveUserIdList.isEmpty()) &&
                (receiveGroupIdList==null||receiveGroupIdList.isEmpty())){
            throw new DuoJuHeException("请选择转发接收对象(好友或群组)!");
        }
        //用户的会话记录id
        List<String> chatListArr = new ArrayList<>();
        //合并总的接收对象id
        List<SendTalkReq> sendTalkReqList = new ArrayList<>();
        if (receiveGroupIdList!=null&&!receiveGroupIdList.isEmpty()){
            for (String receiveId:receiveGroupIdList){
                //判断群组是否被禁言了
                checkGroupSendMessage(userId,receiveId);
                //构建新集合对象
                SendTalkReq sendTalk = new SendTalkReq();
                sendTalk.setReceiverId(receiveId);
                sendTalk.setTalkType(ImChatEnum.TalkType.GROUP_CHAT.getKey());
                sendTalkReqList.add(sendTalk);
                chatListArr.add(MD5Util.getMD532( userId+receiveId));
            }
        }
        if (receiveUserIdList!=null&&!receiveUserIdList.isEmpty()){
            for (String receiveId:receiveUserIdList){
                SendTalkReq sendTalk = new SendTalkReq();
                sendTalk.setReceiverId(receiveId);
                sendTalk.setTalkType(ImChatEnum.TalkType.PRIVATE_CHAT.getKey());
                sendTalkReqList.add(sendTalk);
                chatListArr.add(MD5Util.getMD532( userId+receiveId));
            }
        }
        //校验用户是否有这些结束对象发布消息权限
        List<ChatUsersChatList> chatUsersChatLists = chatUsersChatListMapper.queryChatUsersChatListByIdList(chatListArr);
        if (chatUsersChatLists.size()!=sendTalkReqList.size()){
            throw new DuoJuHeException(ErrorCodes.PARAM_ERROR);
        }
        //逐条转发
        Integer oneForward = ImChatEnum.ForwardMode.ONE_FORWARD.getKey();
        //如果选择的记录只有一条强制逐条转发
        if (req.getRecordIdList().size()==1){
            req.setForwardMode(oneForward);
        }
        return sendTalkReqList;
    }

    /**
     * 转发消息（多条合并转发）
     */
    public ServiceResult multiMergeForward(SystemUser systemUser, List<ChatTalkRecord> recordList, List<SendTalkReq> sendTalkReqList) throws Exception{
        List<ChatTalkRecord> newRecordList;
        //取出前3条记录  // 默认取前3条聊天记录
        if (recordList.size()>3){
            newRecordList = recordList.subList(0, 3);
        }else {
            newRecordList = new ArrayList<>(recordList);
        }
        //快照对象
        List<ForwardSnapshotRecordRes> snapshotList = new ArrayList<>();
        for (ChatTalkRecord oldRecord:newRecordList){
            ForwardSnapshotRecordRes snapshotRecordRes = new ForwardSnapshotRecordRes();
            snapshotRecordRes.setOldRealName(oldRecord.getRealName());
            snapshotRecordRes.setOldRecordId(oldRecord.getRecordId());
            snapshotRecordRes.setOldUserId(oldRecord.getUserId());
            snapshotRecordRes.setOldContent(BuildMessageUtils.getLastMessage(oldRecord));
            snapshotList.add(snapshotRecordRes);
        }
        //消息内容
        String snapshot = JSON.toJSONString(snapshotList);
        //消息类型
        Integer msgType = ImChatEnum.TalkMessageType.FORWARD_MESSAGE.getKey();
        //批量插入消息对象
        List<ChatTalkRecord> talkRecordList = new ArrayList<>();
        //批量插入转发消息对象
        List<ChatTalkRecordForward> forwardList = new ArrayList<>();
        //转发记录id
        List<String> forwardRecordIds = recordList.stream().map(ChatTalkRecord::getRecordId).collect(Collectors.toList());
        for (SendTalkReq talkReq:sendTalkReqList){
            //构建消息记录
            ChatTalkRecord recordNew = buildChatTalkRecord(msgType,talkReq,systemUser);
            recordNew.setContent(snapshot);
            talkRecordList.add(recordNew);
            //构建转发会话记录
            ChatTalkRecordForward recordForward = new ChatTalkRecordForward();
            recordForward.setForwardId(recordNew.getRecordId());
            recordForward.setRecordId(recordNew.getRecordId());
            recordForward.setUserId(recordNew.getUserId());
            recordForward.setCreateUserId(recordNew.getCreateUserId());
            recordForward.setCreateTime(recordNew.getCreateTime());
            recordForward.setSnapshot(recordNew.getContent());
            recordForward.setForwardRecordIds(StringUtils.join(forwardRecordIds,SingleStringConstant.COMMA));
            forwardList.add(recordForward);
        }
        //批量插入会话消息
        if (!talkRecordList.isEmpty()){
            chatTalkRecordMapper.batchInsertListUseAllCols(talkRecordList);
        }
        //批量插入转发消息
        if (!forwardList.isEmpty()){
            chatTalkRecordForwardMapper.batchInsertListUseAllCols(forwardList);
        }
        //转发对象快照
        ForwardRes forward = new ForwardRes(forwardRecordIds.size(),snapshotList);
        //发送消息
        for (ChatTalkRecord record:talkRecordList){
            //构建发送消息
            MessageBodyRes bodyRes = BuildMessageUtils.buildMessageBodyRes(record);
            bodyRes.setForward(forward);
            //保存最后的消息记录
            handleLastMessage(record);
            //发送消息到各个订阅端
            handleSendChatSubscribe(bodyRes);
        }
        return ServiceResult.ok(ErrorCodes.SUCCESS);
    }

    /**
     * 转发消息（多条拆分转发）
     */
    public ServiceResult multiSplitForward(SystemUser systemUser,List<ChatTalkRecord> recordList,List<SendTalkReq> sendTalkReqList) throws Exception{
        //过滤出待转发记录里面含有 代码消息 文件消息的记录id出来
        //文件消息
        Integer file = ImChatEnum.TalkMessageType.FILE_MESSAGE.getKey();
        //过滤出允许转发的消息出来
        List<String> fileIdList = recordList.stream().filter(e->file.equals(e.getMsgType())).map(ChatTalkRecord::getRecordId).collect(Collectors.toList());
        Map<String,ChatTalkRecordFile> fileMap = new HashMap<>();
        if (!fileIdList.isEmpty()){
            fileMap = chatTalkRecordFileMapper.queryChatTalkRecordFileListByFileIdList(fileIdList).stream().collect(Collectors.toMap(ChatTalkRecordFile::getFileId, f -> f));
        }
        //代码消息
        Integer code = ImChatEnum.TalkMessageType.CODE_MESSAGE.getKey();
        List<String> codeIdList = recordList.stream().filter(e->code.equals(e.getMsgType())).map(ChatTalkRecord::getRecordId).collect(Collectors.toList());
        Map<String,ChatTalkRecordCode> codeMap = new HashMap<>();
        if (!codeIdList.isEmpty()){
            codeMap = chatTalkRecordCodeMapper.queryChatTalkRecordCodeListByCodeIdList(codeIdList).stream().collect(Collectors.toMap(ChatTalkRecordCode::getCodeId, c -> c));
        }
        //当前登录人
        String userId = systemUser.getUserId();
        //批量插入消息对象
        List<ChatTalkRecord> talkRecordList = new ArrayList<>();

        //批量插入文件对象
        List<ChatTalkRecordFile> talkRecordFileList = new ArrayList<>();

        //批量插入代码对象
        List<ChatTalkRecordCode> talkRecordCodeList = new ArrayList<>();

        //最终分发对象集合
        List<MultiForwardRecordRes> multiForwardRecordResList = new ArrayList<>();
        for (ChatTalkRecord recordOld:recordList){
            //消息记录id
            String oldRecordId = recordOld.getRecordId();
            //消息内容
            String content = recordOld.getContent();
            //消息类型
            Integer msgType = recordOld.getMsgType();
            for (SendTalkReq talkReq:sendTalkReqList){
                //构建消息记录
                ChatTalkRecord recordNew = buildChatTalkRecord(msgType,talkReq,systemUser);
                recordNew.setContent(content);
                //消息记录id
                String recordId = recordNew.getRecordId();
                //待订阅分发的记录
                MultiForwardRecordRes multiForwardRecordRes = new MultiForwardRecordRes();
                multiForwardRecordRes.setChatTalkRecord(recordNew);
                if (file.equals(msgType)){
                    ChatTalkRecordFile fileRecord = fileMap.get(oldRecordId);
                    if (fileRecord!=null&&StringUtils.isNotBlank(fileRecord.getFileId())){
                        //消息文件对象
                        ChatTalkRecordFile recordFile = new ChatTalkRecordFile();
                        //拷贝对象到新对象中
                        BeanUtils.copyProperties(recordFile,fileRecord);
                        recordFile.setFileId(recordId);
                        recordFile.setRecordId(recordId);
                        recordFile.setUserId(userId);
                        recordFile.setCreateUserId(userId);
                        talkRecordFileList.add(recordFile);
                        multiForwardRecordRes.setChatTalkRecordFile(recordFile);
                    }
                }else if (code.equals(msgType)){
                    ChatTalkRecordCode codeRecord = codeMap.get(oldRecordId);
                    if (codeRecord!=null&&StringUtils.isNotBlank(codeRecord.getCodeId())){
                        //代码片段对象
                        ChatTalkRecordCode recordCode = new ChatTalkRecordCode();
                        //拷贝对象到新对象中
                        BeanUtils.copyProperties(recordCode,codeRecord);
                        recordCode.setCodeId(recordId);
                        recordCode.setRecordId(recordId);
                        recordCode.setUserId(userId);
                        recordCode.setCreateUserId(userId);
                        talkRecordCodeList.add(recordCode);
                        multiForwardRecordRes.setChatTalkRecordCode(recordCode);
                    }
                }
                talkRecordList.add(recordNew);
                //待订阅分发的记录
                multiForwardRecordResList.add(multiForwardRecordRes);
            }
        }
        //批量插入会话消息
        if (!talkRecordList.isEmpty()){
            chatTalkRecordMapper.batchInsertListUseAllCols(talkRecordList);
        }
        //批量插入文件消息
        if (!talkRecordFileList.isEmpty()){
            chatTalkRecordFileMapper.batchInsertListUseAllCols(talkRecordFileList);
        }
        //批量插入代码片段消息
        if (!talkRecordCodeList.isEmpty()){
            chatTalkRecordCodeMapper.batchInsertListUseAllCols(talkRecordCodeList);
        }
        //发送消息
        for (MultiForwardRecordRes recordRes:multiForwardRecordResList){
            //消息体
            ChatTalkRecord record = recordRes.getChatTalkRecord();
            //文件消息
            ChatTalkRecordFile chatTalkRecordFile = recordRes.getChatTalkRecordFile();
            //代码消息
            ChatTalkRecordCode chatTalkRecordCode = recordRes.getChatTalkRecordCode();
            //构建发送消息
            MessageBodyRes bodyRes = BuildMessageUtils.buildMessageBodyRes(record);
            //文件消息
            if (chatTalkRecordFile!=null&&StringUtils.isNotBlank(chatTalkRecordFile.getFileId())){
                bodyRes.setFile(new FileRes(chatTalkRecordFile));
            }
            //代码片段
            if (chatTalkRecordCode!=null&&StringUtils.isNotBlank(chatTalkRecordCode.getCodeId())){
                bodyRes.setCodeBlock(new CodeBlockRes(chatTalkRecordCode));
            }
            //保存最后的消息记录
            handleLastMessage(record);
            //发送消息到各个订阅端
            handleSendChatSubscribe(bodyRes);
        }
        return ServiceResult.ok(ErrorCodes.SUCCESS);
    }



    /**
     * 检查查询用户聊天记录参数校验
     * @param userId
     * @param talkType
     * @param receiverId
     */
    public Date getQueryChatTalkRecordEndTime(String userId,Integer talkType,String receiverId){
        //主键ID 当前用户id和接收id的MD5值
        String id = MD5Util.getMD532(userId+receiverId);
        if (ImChatEnum.TalkType.PRIVATE_CHAT.getKey().equals(talkType)){
            ChatUsersFriends friends = chatUsersFriendsMapper.selectByPrimaryKey(id);
            if (friends==null){
                throw new DuoJuHeException(ErrorCodes.NOT_FRIENDS_NO_TALK_RECORD_ERROR);
            }
            return friends.getUnfriendTime();
        }else {
            ChatGroupUser groupUser = chatGroupUserMapper.selectByPrimaryKey(id);
            if (groupUser==null){
                throw new DuoJuHeException(ErrorCodes.NOT_GROUP_USER_NO_TALK_RECORD_ERROR);
            }
            return groupUser.getJoinGroupTime();
        }
    }

    /**
     * 检查查询用户聊天记录参数校验
     * @param userId
     * @param talkType
     * @param receiverId
     */
    public void checkQueryChatTalkRecordParam(String userId,Integer talkType,String receiverId){
        //主键ID 当前用户id和接收id的MD5值
        String id = MD5Util.getMD532(userId+receiverId);
        if (ImChatEnum.TalkType.PRIVATE_CHAT.getKey().equals(talkType)){
            ChatUsersFriends friends = chatUsersFriendsMapper.selectByPrimaryKey(id);
            if (friends==null){
                throw new DuoJuHeException(ErrorCodes.NOT_FRIENDS_NO_TALK_RECORD_ERROR);
            }
        }else {
            ChatGroupUser groupUser = chatGroupUserMapper.selectByPrimaryKey(id);
            if (groupUser==null){
                throw new DuoJuHeException(ErrorCodes.NOT_GROUP_USER_NO_TALK_RECORD_ERROR);
            }
        }
    }

    /**
     * 键盘事件
     * @param socketSessionUser
     */
    public void onConsumeKeyboard(JSONObject jsonObject,SocketSessionUser socketSessionUser){
        if (jsonObject==null){
            return;
        }
        //获取消息内容
        JSONObject jsonData = jsonObject.getJSONObject("data");
        //发送者id
        String senderId = jsonData.getString("senderId");
        //接收对象id
        String receiverId = jsonData.getString("receiverId");
        KeyboardMessageDto keyboardMessageDto = new KeyboardMessageDto(senderId,receiverId);
        SubscribeHandleDto<KeyboardMessageDto> subscribeHandleDto = new SubscribeHandleDto<KeyboardMessageDto>();
        subscribeHandleDto.setEventType(EventCodes.EVENT_KEYBOARD.getEvent());
        subscribeHandleDto.setMessageData(keyboardMessageDto);
        sendChatSubscribeUtil.sendImSubscribeMessage(subscribeHandleDto);
    }


    /**
     * 在线状态处理
     * @param onlineStatus 是在线标识
     * @param socketSessionUser
     */
    public void onConsumeOnlineStatus(Integer onlineStatus,SocketSessionUser socketSessionUser){
        //当前用户id
        String userId = socketSessionUser.getUserId();
        // 判断是否存在异地登录
        boolean isOnline = SocketSessionCache.checkSocketSessionUserIsOnlineByUserId(userId);
        //发送上线通知
        if (!isOnline) {
            OnlineStatusMessageDto onlineStatusMessageDto = new OnlineStatusMessageDto(userId,onlineStatus);
            SubscribeHandleDto<OnlineStatusMessageDto> subscribeHandleDto = new SubscribeHandleDto<OnlineStatusMessageDto>();
            subscribeHandleDto.setEventType(EventCodes.EVENT_ONLINE_STATUS.getEvent());
            subscribeHandleDto.setMessageData(onlineStatusMessageDto);
            sendChatSubscribeUtil.sendImSubscribeMessage(subscribeHandleDto);
        }
    }


    /**
     * 处理消息聊天记录
     * @param talkRecordDto
     */
    public void handleChatTalkRecord(ChatTalkRecordDto talkRecordDto){
        //消息记录id
        String recordId = talkRecordDto.getRecordId();
        //消息类型
        Integer msgType = talkRecordDto.getMsgType();
        if (ImChatEnum.TalkMessageType.FILE_MESSAGE.getKey().equals(msgType)){
            ChatTalkRecordFile  chatTalkRecordFile = chatTalkRecordFileMapper.selectByPrimaryKey(recordId);
            if (chatTalkRecordFile!=null){
                talkRecordDto.setFile(new FileRes(chatTalkRecordFile));
            }
        }else  if (ImChatEnum.TalkMessageType.CODE_MESSAGE.getKey().equals(msgType)){
            ChatTalkRecordCode chatTalkRecordCode = chatTalkRecordCodeMapper.selectByPrimaryKey(recordId);
            if (chatTalkRecordCode!=null){
                talkRecordDto.setCodeBlock(new CodeBlockRes(chatTalkRecordCode));
            }
        }else  if (ImChatEnum.TalkMessageType.GROUP_INVITE_MESSAGE.getKey().equals(msgType)){
            ChatTalkRecordInvite invite = chatTalkRecordInviteMapper.selectByPrimaryKey(recordId);
            if (invite!=null){
                talkRecordDto.setInvite(BuildMessageUtils.buildRecordInviteToInviteRes(invite));
            }
        }else  if (ImChatEnum.TalkMessageType.FORWARD_MESSAGE.getKey().equals(msgType)){
            ChatTalkRecordForward recordForward = chatTalkRecordForwardMapper.selectByPrimaryKey(recordId);
            if (recordForward!=null){
                //转发对象快照
                List<ForwardSnapshotRecordRes> snapshotList = new ArrayList<>();
                //总条数
                List<String> forwardRecordIds = new ArrayList<>();
                if (StringUtils.isNotBlank(recordForward.getSnapshot())){
                    snapshotList = JSON.parseObject(recordForward.getSnapshot(), new TypeReference<ArrayList<ForwardSnapshotRecordRes>>(){});
                }
                if (StringUtils.isNotBlank(recordForward.getForwardRecordIds())){
                    forwardRecordIds = Arrays.asList(recordForward.getForwardRecordIds().split(SingleStringConstant.COMMA));
                }
                talkRecordDto.setForward(new ForwardRes(forwardRecordIds.size(),snapshotList));
            }
        }else  if (ImChatEnum.TalkMessageType.VOTE_MESSAGE.getKey().equals(msgType)){
            //查询投票信息
            ChatTalkRecordVote talkRecordVote = chatTalkRecordVoteMapper.selectByPrimaryKey(recordId);
            if (talkRecordVote!=null){
                //查询投票答案信息
                List<ChatTalkRecordVoteAnswer> voteAnswerList = chatTalkRecordVoteAnswerMapper.queryChatTalkRecordVoteAnswerByVoteId(talkRecordVote.getVoteId());
                //回答用户ids
                List<String> userIdList =  voteAnswerList.stream().map(ChatTalkRecordVoteAnswer::getUserId).collect(Collectors.toList());
                //回答内容体list
                List<String> answerList =  voteAnswerList.stream().map(ChatTalkRecordVoteAnswer::getAnswerOption).collect(Collectors.toList());
                //选项内容
                ArrayList<AnswerOptionRes> optionList  = new ArrayList<>();
                //内容字符串
                String answerOptionContent = talkRecordVote.getAnswerOptionContent();
                //统计
                Map<String,Integer> statisticsResMap = new HashMap<>();
                if (StringUtils.isNotBlank(answerOptionContent)){
                    optionList = JSON.parseObject(answerOptionContent, new TypeReference<ArrayList<AnswerOptionRes>>(){});
                    for(AnswerOptionRes optionRes:optionList){
                        String key = optionRes.getKey();
                        //key统计值
                        int keyNum = 0;
                        for (String answer:answerList){
                            List<String> answerArrList = Arrays.asList(answer.split(SingleStringConstant.COMMA));
                            if (answerArrList.contains(key)){
                                keyNum++;
                            }
                        }
                        //统计
                        statisticsResMap.put(key,keyNum);
                    }
                }
                //投票统计
                StatisticsRes statisticsRes = new StatisticsRes();
                statisticsRes.setCount(voteAnswerList.size());
                statisticsRes.setOptions(statisticsResMap);
                //投票详情
                DetailRes detailRes = new DetailRes();
                detailRes.setId(talkRecordVote.getVoteId());
                detailRes.setAnswerNum(talkRecordVote.getAnswerNum());
                detailRes.setAnsweredNum(talkRecordVote.getAnsweredNum());
                detailRes.setTitle(talkRecordVote.getVoteTitle());
                detailRes.setStatus(talkRecordVote.getVoteStatus());
                detailRes.setAnswerMode(talkRecordVote.getAnswerMode());
                detailRes.setAnswerOptionList(optionList);
                VoteRes voteRes = new VoteRes();
                voteRes.setStatistics(statisticsRes);
                voteRes.setDetail(detailRes);
                voteRes.setVoteUsers(userIdList);
                talkRecordDto.setVote(voteRes);
            }
        }
    }


    /**
     * 根据消息处理最后一条聊天记录
     * @param record
     */
    public void handleLastMessage(ChatTalkRecord record){
        ThreadUtils.execute(() -> {
            try {
                if (record==null){
                    return;
                }
                //发布人id
                String userId = record.getUserId();
                //接收人id
                String receiverId = record.getReceiverId();
                List<ChatUsersChatList> chatUsersChatLists = new ArrayList<>();
                if (ImChatEnum.TalkType.PRIVATE_CHAT.getKey().equals(record.getTalkType())){
                    //私聊
                    ChatUsersChatList usersChatList1 = chatUsersChatListMapper.selectByPrimaryKey(MD5Util.getMD532(userId+receiverId));
                    if (usersChatList1!=null){
                        chatUsersChatLists.add(usersChatList1);
                    }
                    //好友会话记录
                    ChatUsersChatList usersChatList2 = chatUsersChatListMapper.selectByPrimaryKey(MD5Util.getMD532(receiverId+userId));
                    if (usersChatList2!=null){
                        chatUsersChatLists.add(usersChatList2);
                    }
                }else if (ImChatEnum.TalkType.GROUP_CHAT.getKey().equals(record.getTalkType())){
                    //群聊
                    List<String> receiverIdList = new ArrayList<>();
                    receiverIdList.add(receiverId);
                    chatUsersChatLists = chatUsersChatListMapper.queryChatUsersChatListByReceiverIdList(receiverIdList);
                }
                //待处理对象集合
                for (ChatUsersChatList chatList:chatUsersChatLists){
                    chatUsersChatListMapper.updateByPrimaryKeySelective(BuildMessageUtils.buildLastChatUsersChatList(chatList,record));
                }
            }catch (Exception e){
                log.error("根据消息处理最后一条聊天记录出现异常",e);
            }
        });
    }

    /**
     * 发送消息订阅到通道
     * @param bodyRes
     */
    public void handleSendChatSubscribe(MessageBodyRes bodyRes){
        TalkMessageDto messageDto = new TalkMessageDto(bodyRes);
        SubscribeHandleDto<TalkMessageDto> subscribeHandleDto = new SubscribeHandleDto<TalkMessageDto>();
        subscribeHandleDto.setEventType(EventCodes.EVENT_TALK.getEvent());
        subscribeHandleDto.setMessageData(messageDto);
        sendImSubscribeMessage(subscribeHandleDto);
    }


    /**
     * 发布订阅
     * @param subscribeHandleDto
     */
    public void sendImSubscribeMessage(SubscribeHandleDto subscribeHandleDto){
        sendChatSubscribeUtil.sendImSubscribeMessage(subscribeHandleDto);
    }



}
